package com.joysuch.wwyt.attendant.service.impl;

import cn.hutool.core.util.IdUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.joysuch.wwyt.attendant.bean.AttendantAreaBean;
import com.joysuch.wwyt.attendant.bean.AttendantAreaReqBean;
import com.joysuch.wwyt.attendant.bean.AttendantPlanDetailBean;
import com.joysuch.wwyt.attendant.bean.vo.PolygonVo;
import com.joysuch.wwyt.attendant.bean.vo.RailReqVo;
import com.joysuch.wwyt.attendant.entity.AttendantArea;
import com.joysuch.wwyt.attendant.enums.AreaSyncEnum;
import com.joysuch.wwyt.attendant.mapper.AttendantAreaMapper;
import com.joysuch.wwyt.attendant.mapper.AttendantPlanMapper;
import com.joysuch.wwyt.attendant.service.AttendantAreaService;
import com.joysuch.wwyt.attendant.service.AttendantPlanService;
import com.joysuch.wwyt.attendant.service.OpenPlatformService;
import com.joysuch.wwyt.bp.bean.PositionCheckBean;
import com.joysuch.wwyt.bp.entity.BpDepart;
import com.joysuch.wwyt.bp.service.BpDepartService;
import com.joysuch.wwyt.common.constant.Constant;
import com.joysuch.wwyt.core.common.ajax.ResultBean;
import com.joysuch.wwyt.core.common.util.JsonUtil;
import com.joysuch.wwyt.core.entity.BaseUser;
import com.joysuch.wwyt.core.enums.Status;
import com.joysuch.wwyt.core.exception.ApiBusinessException;
import com.joysuch.wwyt.core.exception.ApiCoreException;
import com.joysuch.wwyt.core.repository.BaseUserDao;
import com.joysuch.wwyt.patrol.entity.PatrolCheckPoint;
import com.joysuch.wwyt.patrol.entity.bean.LocationBean;
import com.joysuch.wwyt.patrol.entity.bean.LocationPointsBean;
import com.joysuch.wwyt.util.RegionUtil;
import com.joysuch.wwyt.workflow.api.bean.TrajectoryLastLocationResp;
import com.joysuch.wwyt.workflow.api.service.PersonTrajectoryService;
import com.joysuch.wwyt.workflow.bean.CardLineBean;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.text.ParseException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * 跟班区域
 *
 * @author xsx
 * @version 1.0
 * @date 2023/2/15 16:53
 */
@Service
@Transactional(rollbackFor = Exception.class)
@Slf4j
public class AttendantAreaServiceImpl extends ServiceImpl<AttendantAreaMapper, AttendantArea> implements AttendantAreaService {

    @Autowired
    private AttendantAreaMapper attendantAreaMapper;

    @Autowired
    private BaseUserDao userDao;

    @Autowired
    private PersonTrajectoryService personTrajectory;

    @Autowired
    private OpenPlatformService openPlatformService;

    @Autowired
    private BpDepartService bpDepartService;

    @Autowired
    private AttendantPlanMapper attendantPlanMapper;

    @Override
    public List<AttendantArea> selectByIds(List<Long> ids) {
        List<AttendantArea> list = attendantAreaMapper.selectBatchIds(ids);
        return list;
    }

    @Override
    public void saveEntity(AttendantAreaBean bean) throws ParseException {
        List<AttendantArea> list = attendantAreaMapper.selectByName(bean.getName(), null);
        if (!list.isEmpty()) {
            throw new IllegalArgumentException("区域名称重复");
        }
        AttendantArea area = new AttendantArea();
        BeanUtils.copyProperties(bean, area);
        attendantAreaMapper.insert(area);
    }

    @Override
    public void updateEntity(AttendantAreaBean bean) throws ApiCoreException {
        List<AttendantArea> list = attendantAreaMapper.selectByName(bean.getName(), bean.getId());
        if (!list.isEmpty()) {
            throw new IllegalArgumentException("区域名称重复");
        }
        AttendantArea area = new AttendantArea();
        BeanUtils.copyProperties(bean, area);
        UpdateWrapper<AttendantArea> updateWrapper=new UpdateWrapper<>();
        updateWrapper.eq("id",area.getId());
        updateWrapper.set("coordinates",area.getCoordinates());
        updateWrapper.set("name",area.getName());
        updateWrapper.set("dept_id",area.getDeptId());
        updateWrapper.set("update_time",new Date());
//        attendantAreaMapper.updateById(area);
        this.update(updateWrapper);
        updateSyncArea(bean);

    }


    public void updateSyncArea(AttendantAreaBean bean) throws ApiCoreException {
        String coordinates = bean.getCoordinates();
        LocationBean locationBean = JSONObject.parseObject(coordinates, LocationBean.class);
        RailReqVo vo = new RailReqVo();
        vo.setName(bean.getName());
        vo.setFloorNo("Floor" + locationBean.getFloorId());
        vo.setMapType(2);
        List<PolygonVo> list = new ArrayList<>();
        List<LocationPointsBean> points = locationBean.getPoints();
        for (LocationPointsBean point : points) {
            PolygonVo polygonVo = new PolygonVo();
            polygonVo.setLatitude(point.getY());
            polygonVo.setLongitude(point.getX());
            list.add(polygonVo);
        }
        vo.setPolygon(list);
        AttendantArea old = attendantAreaMapper.selectById(bean.getId());
        if (StringUtils.isNotBlank(old.getPlatformAreaId()) && old.getIsSync() == 1) {
            vo.setUuid(old.getPlatformAreaId());
            openPlatformService.updateSyncArea(vo);
        }
    }

    @Override
    public void saveEntitys(List<AttendantAreaBean> beans) throws ParseException {
        for (AttendantAreaBean bean : beans) {
            List<AttendantArea> list = attendantAreaMapper.selectByName(bean.getName(), bean.getId());
            if (!list.isEmpty()) {
                throw new IllegalArgumentException("区域名称重复");
            }
        }
        List<AttendantArea> list = new ArrayList<>();
        for (AttendantAreaBean bean : beans) {
            AttendantArea area = new AttendantArea();
            BeanUtils.copyProperties(bean, area);
            list.add(area);
        }
        this.saveBatch(list);
    }

    @Override
    public AttendantAreaBean findById(Long id) {
        AttendantAreaBean bean = new AttendantAreaBean();
        AttendantArea area = attendantAreaMapper.selectById(id);
        if (area.getDeptId()!=null){
            BpDepart depart = bpDepartService.findById(area.getDeptId());
            if (depart!=null){
                bean.setDeptName(depart.getName());
            }
        }
        BeanUtils.copyProperties(area, bean);
        return bean;
    }

    @Override
    public Page<AttendantAreaBean> selectPage(AttendantAreaReqBean bean) {
        Page<AttendantAreaBean> page = new Page<>(bean.getPage() + 1, bean.getSize());
        Page<AttendantAreaBean> resultPage = attendantAreaMapper.selectAttendantAreaBean(page, bean);
        if (resultPage!=null) {
            for (AttendantAreaBean record : resultPage.getRecords()) {
                record.setSyncName(AreaSyncEnum.find(record.getIsSync()).getDesc());
            }
        }
        resultPage.setTotal(page.getTotal());
        return resultPage;
    }

    @Override
    public void deleteEntity(Long id) throws ApiCoreException {
        AttendantArea attendantArea = attendantAreaMapper.selectById(id);
        Long count = attendantPlanMapper.selectByAreaId(attendantArea.getId());
        if (count>0){
            throw new IllegalArgumentException("该区域有跟班计划，不能删除");
        }
        attendantArea.setDeleteFlag("1");
        if (attendantArea.getIsSync() == 1 && StringUtils.isNotBlank(attendantArea.getPlatformAreaId())) {
            openPlatformService.deleteArea(attendantArea.getPlatformAreaId());
        }
        attendantAreaMapper.updateById(attendantArea);
    }

    @Override
    public PositionCheckBean position(Long areaId, Long userId) throws ApiCoreException {
        // 检查点位置处理
        AttendantArea area = baseMapper.selectById(areaId);
        String pointLocationStr = area.getCoordinates();
        if (StringUtils.isBlank(pointLocationStr)) {
            throw new IllegalArgumentException("该检查点没有位置信息");
        }
        // 检查点位置
        LocationBean pointLocation = JsonUtil.fromJson(pointLocationStr, LocationBean.class);
        // 位置点位数组
        List<LocationPointsBean> points = pointLocation.getPoints();
        Double[] pointLons = new Double[points.size()];
        Double[] pointLats = new Double[points.size()];
        getCoordinateArr(points, pointLons, pointLats);

        // 人员位置处理
        BaseUser user = userDao.findById(userId).get();
        String sn = user.getSn();
        // 定位卡号不为空
        if (org.springframework.util.StringUtils.isEmpty(sn)) {
            throw new IllegalArgumentException(Status.USER_SN_IS_NULL.getMsg());
        }
        TrajectoryLastLocationResp userLocation = personTrajectory.getLastLocation(sn, null, IdUtil.simpleUUID());
        // 未获取到人员位置或最后一个点位在十分钟之外
        if (userLocation == null || (new Date().getTime() - userLocation.getTimestampMillisecond()) > 1000 * 60 * 10) {
            log.error("人员位置获取失败：{}", userLocation);
            return new PositionCheckBean(false, null);
        }
        String userLocationStr = JsonUtil.toJson(userLocation);
        // 用户位置处理
        Double userLon = userLocation.getLongitude();
        Double userLat = userLocation.getLatitude();
        String floorNo = userLocation.getFloorNo();
        // 开放平台楼层转换
        Long floorId = Long.parseLong(floorNo.replace(Constant.FLOOR_REPLACE_STR, Constant.EMPTY_STR));
        if (!floorId.equals(pointLocation.getFloorId())) {
            log.error("位置校验失败-楼层异常");
            return new PositionCheckBean(false, null);
        }
        boolean inPolygon = RegionUtil.isInPolygon(userLon, userLat, pointLons, pointLats);
        return new PositionCheckBean(inPolygon, userLocationStr);
    }

    @Override
    public List<Long> selectByName(String areaName) {
        return baseMapper.selectIdsByName(areaName);
    }

    @Override
    public String findRailId(Long areaId) {
        return baseMapper.findRailId(areaId);
    }

    @Override
    public Long selectIdByName(String areaName) {
        return baseMapper.selectIdByName(areaName);
    }

    @Override
    public List<CardLineBean> selectList(String name) {
        return baseMapper.selectAreas(name);
    }

    @Override
    public ResultBean syncArea(Long id) {
        AttendantArea area = baseMapper.selectById(id);
        if (area.getIsSync() == 1) {
            return ResultBean.defaultSuccessResult();
        }
        String coordinates = area.getCoordinates();
        if (StringUtils.isBlank(coordinates)) {
            return ResultBean.defaultSuccessResult();
        }
        LocationBean locationBean = JSONObject.parseObject(coordinates, LocationBean.class);
        RailReqVo vo = new RailReqVo();
        vo.setName(area.getName());
        vo.setFloorNo("Floor" + locationBean.getFloorId());
        vo.setMapType(2);
        List<PolygonVo> list = new ArrayList<>();
        List<LocationPointsBean> points = locationBean.getPoints();
        for (LocationPointsBean point : points) {
            PolygonVo polygonVo = new PolygonVo();
            polygonVo.setLatitude(point.getY());
            polygonVo.setLongitude(point.getX());
            list.add(polygonVo);
        }
        vo.setPolygon(list);
//        if (StringUtils.isNotBlank(area.getPlatformAreaId())) {
//            vo.setUuid(area.getPlatformAreaId());
//        }
        try {
            String platformAreaId = openPlatformService.syncArea(vo);
            area.setPlatformAreaId(platformAreaId);
            area.setIsSync(1);
            this.updateById(area);
            return ResultBean.defaultSuccessResult();
        } catch (ApiCoreException e) {
            return ResultBean.fail(500,"同步区域失败");
        }
    }

    private void getCoordinateArr(List<LocationPointsBean> points, Double[] lonArr, Double[] latArr) {
        int i = 0;
        for (LocationPointsBean each : points) {
            lonArr[i] = each.getX();
            latArr[i] = each.getY();
            i++;
        }
    }
}
